package drawables;



import java.awt.Color;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.awt.image.BufferedImageOp;
import java.awt.image.ColorModel;

/**
 * 
 * @author David X. Wang
 *
 */
public class BoxBlurFilter implements BufferedImageOp {
	
	protected int radiusX, radiusY;
	
	public void setRadiusX(int x){
		radiusX = x;
	}
	
	public void setRadiusY(int y){
		radiusY = y;
	}

	@Override
	public BufferedImage filter(BufferedImage src, BufferedImage dest) {
		if(dest == null)
			dest = createCompatibleDestImage(src, null);
		int width = src.getWidth();
		int height = src.getHeight();
		int[] pixels = src.getRGB(0, 0, width, height, null, 0, width);
		//convert to 2D Color array
		Color[][] temp1 = new Color[width][height];
		for(int i=0; i<pixels.length; i++){
			int x = i % width;
			int y = i / width;
			temp1[x][y] = new Color(pixels[i]);
		}
		//blur vertical
		Color[][] temp2 = new Color[height][width];
		for(int x = 0; x<width; x++)
			for(int y = 0; y<height; y++)
				temp2[y][x] = blur(temp1[x], y, radiusY, false);
		//blur horizontal
		for(int y = 0; y<height; y++)
			for(int x = 0; x<width; x++)
				pixels[y*width + x] = blur(temp2[y], x, radiusX, true).getRGB();
		dest.setRGB(0, 0, width, height, pixels, 0, width);
		return dest;
	}
	
	private Color blur(Color[] pixels, int index, int radius, boolean horizontal){
		if(horizontal && radiusX<2)
			return pixels[index];
		else if(!horizontal && radiusY<2)
			return pixels[index];
		Color[] blur = new Color[radius*2 + 1];
		for(int i=0, j=index-radius; j<=index+radius; i++, j++){
			if(j < 0)
				blur[i] = pixels[0];
			else if(j >= pixels.length)
				blur[i] = pixels[pixels.length - 1];
			else
				blur[i] = pixels[j];
		}
		return averageColor(horizontal, blur);
	}
	
	protected Color averageColor(boolean horizontal, Color ... colors){
		int r = 0, g = 0, b = 0;
		for(Color color : colors){
			r += color.getRed();
			g += color.getGreen();
			b += color.getBlue();
		}
		return new Color(r/colors.length, g/colors.length, b/colors.length);
	}

	@Override
	public Rectangle2D getBounds2D(BufferedImage src) {
		return new Rectangle(src.getWidth(), src.getHeight());
	}

	@Override
	public BufferedImage createCompatibleDestImage(BufferedImage src, ColorModel destCM) {
		return new BufferedImage(src.getWidth(), src.getHeight(), src.getType());
	}

	@Override
	public Point2D getPoint2D(Point2D srcPt, Point2D dstPt) {
		return null;
	}

	@Override
	public RenderingHints getRenderingHints() {
		return null;
	}

}
